package com.shop.config.timer.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shop.common.BeanUtil;
import com.shop.entity.QuartzConfigDo;
import com.shop.mapper.QuartzConfigDoMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;

import java.util.*;

@Slf4j
@Component
public class DataContainerImpl implements Job {

    private Scheduler scheduler = null;

    private List<QuartzConfigDo> quartzConfigDos = null;


    public List<QuartzConfigDo> getQuartzConfigDos() {
        if (quartzConfigDos == null) return new ArrayList<>();
        return quartzConfigDos;
    }

    /**
     * 创建调度器
     *
     * @return
     * @throws Exception
     */
    public Scheduler getScheduler() throws Exception {
        if (scheduler == null) {
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            return schedulerFactory.getScheduler();
        }
        return scheduler;
    }


    @SneakyThrows
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        //1、获取任务配置
        this.selectQuartzConfig();
        //2、创建调度器
        Scheduler scheduler = this.getScheduler();

        // 4、创建任务和触发器
        List<QuartzConfigDo> quartzConfig = this.getQuartzConfigDos();
        if (quartzConfig.size() <= 0) return;
        Map<JobDetail, Set<? extends Trigger>> jobDetailAndTriggerMap = this.getTriggerAndJobDetail(quartzConfig);
        //4、执行
        scheduler.scheduleJobs(jobDetailAndTriggerMap, false);

        log.info("-------- 定时器定时检测任务 ! ------------");
        log.info("-------- > {}", scheduler.getCurrentlyExecutingJobs());
        log.info("-------- > {}", scheduler.getJobGroupNames());
    }


    /**
     * 创建任务和触发器
     *
     * @param quartzConfigDos
     * @return
     * @throws Exception
     */
    private Map<JobDetail, Set<? extends Trigger>> getTriggerAndJobDetail(List<QuartzConfigDo> quartzConfigDos) throws Exception {
        Map<JobDetail, Set<? extends Trigger>> var1 = new HashMap<>();
        for (QuartzConfigDo k : quartzConfigDos) {
            if (!this.checkUpSchedulerIsHasJob(k)) continue;
            Set<Trigger> set = new HashSet<>();
            // 1、创建任务实例
            Class cl = Class.forName(k.getJobImpl());
            JobDetail jobDetail = JobBuilder.newJob(cl)
                    .withIdentity(k.getWithidentityName(), k.getWithidentityGroupName()).build();
            // 2、触发设置时间
            CronScheduleBuilder builder = CronScheduleBuilder.cronSchedule(k.getExecutionTime());
            // 3、构建触发器实例
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(k.getTriggerName(), k.getTriggerGroupName()).startNow()
                    .withSchedule(builder)
                    .build();
            set.add(trigger);
            var1.putIfAbsent(jobDetail, set);
        }
        return var1;
    }

    /**
     * 获取数据库定时任务配置
     *
     * @return
     * @throws Exception
     */
    private void selectQuartzConfig() throws RuntimeException {
        QuartzConfigDoMapper quartzConfigDoMapper = null;
        try {
            quartzConfigDoMapper = BeanUtil.getBeanByBeanName("quartzConfigDoMapper", QuartzConfigDoMapper.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        QueryWrapper<QuartzConfigDo> queryWrapper = new QueryWrapper<>();
        quartzConfigDos = this.getQuartzConfigDos();
        quartzConfigDos = quartzConfigDoMapper.selectList(queryWrapper);
    }

    /**
     * 检查调度器是否已含有此任务
     * <p>
     * 如果不存在该任务 如任务启用 则返回true
     *
     * @return
     */
    private boolean checkUpSchedulerIsHasJob(QuartzConfigDo quartzConfigDo) throws Exception {
        Scheduler scheduler = this.getScheduler();
        JobKey key = new JobKey(quartzConfigDo.getWithidentityName(), quartzConfigDo.getWithidentityGroupName());
        //如果不存在该任务 如任务启用 则返回true ， 未启用则返回false
        log.info("检查任务是否存在 -----》{}", scheduler.checkExists(key));
        if (!scheduler.checkExists(key)) {
            if (quartzConfigDo.getIsEnable().equals("Y")) return true;
            return false;
        }
        //如果存在该任务 如任务启用 则返回false 如果禁用 则停止该任务并移除 返回false
        if (scheduler.checkExists(key)) {
            if (quartzConfigDo.getIsEnable().equals("Y")) return false;
            scheduler.pauseJob(key);
            TriggerKey triggerKey = new TriggerKey(quartzConfigDo.getTriggerName(), quartzConfigDo.getTriggerGroupName());
            scheduler.unscheduleJob(triggerKey);
            return false;
        }
        return false;
    }
}
